package com.udima.reglocation.util;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;

/**
 * Clase para gestionar el posicionamiento vía GPS /WIFI
 * 
 * Configura y realiza la conexión correspondiente y alerta en el caso de que no
 * exista ningún dispositivo activo que permita obtener la posición,
 * redirigiendo al usuario a la pantalla de configuración si lo desea
 * 
 * @author luis
 * 
 */

public class GPSTracker extends Service implements LocationListener {

	private final Context mContext;

	// flag para el estado del dispositivo GPS
	private boolean isGPSEnabled = false;

	// flag para el estado de la red
	private boolean isNetworkEnabled = false;

	// flag para el estado del GPS
	private boolean canGetLocation = false;

	private Location location; // localización
	private double latitude; // latitud
	private double longitude; // longitud

	// La distancia mínima para realizar actualizaciones en metros
	private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // 1 metro

	// El tiempo mínimo entre actualizaciones en milisegundos
	private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minuto

	// Declaración de un Location Manager
	private LocationManager locationManager;

	/**
	 * Constructor de la clase
	 * 
	 * @param context Contexto de la actividad; información global del entorno de la aplicación
	 */
	public GPSTracker(Context context) {
		this.mContext = context;
		getLocation();
	}
	
	/**
	 * 
	 * Método que indica si el GPS está activo
	 * 
	 * @return boolean Indica si el GPS está activo
	 */
	public boolean isGPSEnabled() {
		return isGPSEnabled;
	}

	/**
	 * 
	 * Método que indica si la red está activa
	 * 
	 * @return boolean Indica si la red está activa
	 */
	public boolean isNetworkEnabled() {
		return isNetworkEnabled;
	}

	/**
	 * 
	 * Método que indica si la actividad puede obtener la localización
	 * 
	 * @return boolean Indica si la actividad puede obtener la localización
	 */
	public boolean isCanGetLocation() {
		return canGetLocation;
	}


	/**
	 * Metodo que obtiene la localización en el momento de la consulta del GPS si está activo o de la red en su defecto
	 * 
	 * @return Location Localización obtenida
	 */
	public Location getLocation() {
		try {
			locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);

			// Obteniendo el estado del GPS
			isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

			// obteniendo el estado de la red
			isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

			if (!isGPSEnabled && !isNetworkEnabled) {
				// En este caso ninguno de los dos está habilitado
			} else {

				this.canGetLocation = true;

				if (isGPSEnabled) {
					// se obtiene la posición por gps
					if (isGPSEnabled) {
						if (location == null) {
							locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES,
									MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
							if (locationManager != null) {
								location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
								if (location != null) {
									latitude = location.getLatitude();
									longitude = location.getLongitude();
								}
							}
						}
					}
				} else {
					// si no se ha podido obtener la posición por gps se pide la posición a la red
					if (isNetworkEnabled) {
						locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES,
								MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
						if (locationManager != null) {
							location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
							if (location != null) {
								latitude = location.getLatitude();
								longitude = location.getLongitude();
							}
						}
					}
				}

			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return location;
	}

	/**
	 * Parada en el uso de servicios GPS La llamada a esta función detiene el
	 * uso del dispositivo GPS en la aplicación
	 * */
	public void stopUsingGPS() {
		if (locationManager != null) {
			locationManager.removeUpdates(GPSTracker.this);
		}
	}

	/**
	 * Función para obtener la latitud
	 * 
	 * @return double Valor de la latitud
	 * 
	 * */
	public double getLatitude() {
		if (location != null) {
			latitude = location.getLatitude();
		}

		// devuelve la latitud
		return latitude;
	}

	/**
	 * Función para obtener la longitud
	 * 
	 * @return double Valor de la longitud
	 * 
	 * */
	public double getLongitude() {
		if (location != null) {
			longitude = location.getLongitude();
		}

		// devuelve la longitud
		return longitude;
	}

	/**
	 * Función que comprueba si el GSP/WIFI está activado
	 * 
	 * @return boolean Indica si está activado/desactivado
	 * */
	public boolean canGetLocation() {
		return this.canGetLocation;
	}

	@Override
	/**
	 * 
	 * Método que se ejecuta cuando se registra un cambio en la localización
	 * 
	 * @param localtion Localización pasada por parámetro
	 * 
	 */
	public void onLocationChanged(Location location) {
		if (location != null) {
			this.location = location;
			latitude = location.getLatitude();
			longitude = location.getLongitude();
		}
	}

	@Override
	/**
	 * 
	 * Método que se ejecuta con la desactivación del actual provider
	 * 
	 * @param provider Proveedor de datos actual
	 * 
	 */
	public void onProviderDisabled(String provider) {
	}

	@Override
	/**
	 * 
	 * Método que se ejecuta con la activación del actual provider
	 * 
	 * @param provider Proveedor de datos actual
	 * 
	 */
	public void onProviderEnabled(String provider) {
	}

	@Override
	/**
	 * 
	 * Método que se ejecuta con un cambio de estado en el proveedor
	 * 
	 * @param provider Proveedor de datos actual
	 * @param status Valor del estado
	 * @param extras Estado previo
	 * 
	 */
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	@Override
	/**
	 * 
	 * Método enlace
	 * 
	 */
	public IBinder onBind(Intent arg0) {
		return null;
	}

}